package com.syezon.wifikey.speed;

import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.graphics.Color;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.blankj.utilcode.util.ToastUtils;
import com.syezon.wifikey.R;
import com.syezon.wifikey.base.BaseFragment;
import com.syezon.wifikey.home.ResultHelper;
import com.syezon.wifikey.location.LocationInfo;
import com.syezon.wifikey.location.LocationService;
import com.syezon.wifikey.utils.StatusBarUtil;
import com.syezon.wifikey.utils.Utils;

import java.text.DecimalFormat;
import java.util.Random;

import butterknife.BindView;
import butterknife.OnClick;

public class NewSpeedtestFragment extends BaseFragment {

    @BindView(R.id.rl_main)
    RelativeLayout mRlMain;
    @BindView(R.id.rl_top)
    RelativeLayout mRlTop;

    @BindView(R.id.rl_test_main)
    RelativeLayout mRlTestMain;

    @BindView(R.id.tv_download_speed)
    TextView mTvDownloadSpeed;
    @BindView(R.id.tv_speed_data_use)
    TextView mTvSpeedDataUse;
    @BindView(R.id.chart_download)
    SpeedChartView mLineChartDownload;
    @BindView(R.id.tv_upload_speed)
    TextView mTvUploadSpeed;
    @BindView(R.id.tv_upload_data_use)
    TextView mTvUploadDataUse;
    @BindView(R.id.chart_upload)
    SpeedChartView mLineChartUpload;
    @BindView(R.id.tv_ping)
    TextView mTvPing;
    @BindView(R.id.tv_ping_jitter)
    TextView mTvJitter;
    @BindView(R.id.tv_packet_lose)
    TextView mTvPacketLose;

    @BindView(R.id.ll_speed)
    LinearLayout mLlSpeed;
    @BindView(R.id.tv_current_speed)
    TextView mTvCurrentSpeed;
    @BindView(R.id.tv_speed_msg)
    TextView mTvSpeedMsg;
    @BindView(R.id.tv_ip)
    TextView mTvIp;
    @BindView(R.id.tv_isp)
    TextView mTvIsp;

    @BindView(R.id.speedTestView)
    SpeedTestView3 mSpeedTestView;

    @BindView(R.id.duView)
    DUProgressView mDuProgressView;

    private SpeedTestInfo mSpeedTestInfo;

    private Handler mHandler = new Handler();

    private NewSpeedTestViewModel mSpeedTestViewModel;

    private NetInfoViewModel mNetInfoViewModel;


    public static NewSpeedtestFragment newInstance() {
        NewSpeedtestFragment homeFragment = new NewSpeedtestFragment();
        return homeFragment;
    }


    @Override
    protected int getContentViewLayoutID() {
        return R.layout.app_speed_speedtest;
    }

    @Override
    protected void initViewsAndEvents() {
        StatusBarUtil.setPadding(mContext, mRlMain);
        mSpeedTestInfo = new SpeedTestInfo();

        mRlTestMain.setVisibility(View.VISIBLE);
        initTestView();
        mNetInfoViewModel = ViewModelProviders.of(this).get(NetInfoViewModel.class);
        mNetInfoViewModel.getDeviceInfo();
        mNetInfoViewModel.getDeviceInfoMutableLiveData().observe(this, new Observer<DeviceInfo>() {
            @Override
            public void onChanged(@Nullable DeviceInfo deviceInfo) {
                mTvIp.setText(deviceInfo.getOuterIp());
                mTvIsp.setText(deviceInfo.getIsp());
                mSpeedTestInfo.setIsp(deviceInfo.getIsp());
                mSpeedTestInfo.setOutterIp(deviceInfo.getOuterIp());
            }
        });
        LocationService.getInstance().getLocationLiveData().observe(this, new Observer<LocationInfo>() {
            @Override
            public void onChanged(@Nullable LocationInfo locationInfo) {
                if (locationInfo != null) {
//                    mSpeedTestInfo.setAddress(locationInfo.getCity());
                }
            }
        });
        mSpeedTestViewModel = ViewModelProviders.of(this).get(NewSpeedTestViewModel.class);
        mSpeedTestViewModel.getSpeedTestStepInfoMutableLiveData().observe(this, new Observer<SpeedTestStepInfo>() {
            @Override
            public void onChanged(@Nullable SpeedTestStepInfo speedTestStepInfo) {
                if (speedTestStepInfo != null) {
                    int stepType = speedTestStepInfo.getStepType();
                    switch (stepType) {
                        case SpeedTestStepInfo.STEP_TYPE_CANCEL:
                        case SpeedTestStepInfo.STEP_TYPE_INIT:
                            resetSpeedView();
                            break;
                        case SpeedTestStepInfo.STEP_TYPE_AVERAGE_UPLOAD:
                            uploadSpeedData(speedTestStepInfo);
                            break;
                        case SpeedTestStepInfo.STEP_TYPE_CURRENT_UPLOAD:
                            currentUpload(speedTestStepInfo);
                            break;
                        case SpeedTestStepInfo.STEP_TYPE_START_UPLOAD:
                            mSpeedTestView.setCreditValue(0.0);
                            mDuProgressView.setReverse(false);
                            break;
                        case SpeedTestStepInfo.STEP_TYPE_AVERAGE_SPEED:
                            downloadSpeedData(speedTestStepInfo);
                            break;
                        case SpeedTestStepInfo.STEP_TYPE_CURRENT_SPEED:
                            currentDownload(speedTestStepInfo);
                            break;
                        case SpeedTestStepInfo.STEP_TYPE_START_SPEED:
                            mDuProgressView.setReverse(true);
                            break;
                        case SpeedTestStepInfo.STEP_TYPE_PING_RESULT:
                            pintData(speedTestStepInfo.getPingData());
                            break;
                        case SpeedTestStepInfo.STEP_TYPE_START_LOSE_RATE_RESULT:
                            mTvPacketLose.clearAnimation();
                            mTvPacketLose.startAnimation(AnimationUtils.loadAnimation(mContext, R.anim.alpha_infinite));
                            break;
                        case SpeedTestStepInfo.STEP_TYPE_LOSE_RATE_RESULT:
                            mTvPacketLose.clearAnimation();
                            loseRateData(speedTestStepInfo.getLoseRate());
                            break;
                        case SpeedTestStepInfo.STEP_TYPE_ERROR:
                            endSpeed();
                            ToastUtils.showShort("测速异常，请稍后重试");
                            break;
                    }
                }
            }
        });
        startTest();
    }

    @OnClick({R.id.iv_back})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.iv_back:
                FragmentActivity activity = getActivity();
                if (activity != null) {
                    activity.finish();
                }
                break;
        }
    }

    private void initTestView() {
        mLineChartDownload.setLineColor(Color.parseColor("#FFFFFF"));
        mLineChartUpload.setLineColor(Color.parseColor("#FFFFFF"));
    }

    private void currentUpload(SpeedTestStepInfo speedTestStepInfo) {
        pintData(speedTestStepInfo.getPingData());
        loseRateData(speedTestStepInfo.getLoseRate());
        DecimalFormat decimalFormat = new DecimalFormat("##.##");
        boolean anim = mDuProgressView.isAnim();
        if (!anim) {
            mDuProgressView.setReverse(false);
        }
        mSpeedTestView.setCreditValue(speedTestStepInfo.getUploadSpeed());
        mLineChartUpload.setSpeedSmaplList(speedTestStepInfo.getUploadSampleList());
        mTvCurrentSpeed.setText(decimalFormat.format(speedTestStepInfo.getUploadSpeed()));
    }

    private void currentDownload(SpeedTestStepInfo speedTestStepInfo) {
        pintData(speedTestStepInfo.getPingData());
        loseRateData(speedTestStepInfo.getLoseRate());
        DecimalFormat decimalFormat = new DecimalFormat("##.##");
        boolean reverseAnim = mDuProgressView.isReverseAnim();
        if (!reverseAnim) {
            mDuProgressView.setReverse(true);
        }
        mSpeedTestView.setCreditValue(speedTestStepInfo.getDownloadSpeed());
        mLineChartDownload.setSpeedSmaplList(speedTestStepInfo.getDownloadSampleList());
        mTvCurrentSpeed.setText(decimalFormat.format(speedTestStepInfo.getDownloadSpeed()));
    }

    private void downloadSpeedData(SpeedTestStepInfo speedTestStepInfo) {
        pintData(speedTestStepInfo.getPingData());
        loseRateData(speedTestStepInfo.getLoseRate());
        DecimalFormat decimalFormat = new DecimalFormat("##.##");
        mDuProgressView.reset();
        mSpeedTestInfo.setDlSpeed(speedTestStepInfo.getDownloadSpeed());
        mTvSpeedDataUse.setText(SizeUtils.formartMbSize(speedTestStepInfo.getDownloadDataUse()));
        mTvDownloadSpeed.setText(decimalFormat.format(speedTestStepInfo.getDownloadSpeed()));
        mLineChartDownload.setSpeedSmaplList(speedTestStepInfo.getDownloadSampleList());
    }

    private void uploadSpeedData(SpeedTestStepInfo speedTestStepInfo) {
        downloadSpeedData(speedTestStepInfo);
        DecimalFormat decimalFormat = new DecimalFormat("##.##");
        mDuProgressView.reset();
        mTvUploadSpeed.setText(decimalFormat.format(speedTestStepInfo.getUploadSpeed()));
        mSpeedTestInfo.setUploadSpeed(speedTestStepInfo.getUploadSpeed());
        mLineChartUpload.setSpeedSmaplList(speedTestStepInfo.getUploadSampleList());
        mTvUploadDataUse.setText(SizeUtils.formartMbSize(speedTestStepInfo.getUploadDataUse()));
        mSpeedTestInfo.setTime(System.currentTimeMillis());

        final SpeedTestResult speedTestResult = new SpeedTestResult();
        speedTestResult.setWide(mSpeedTestInfo.getDlSpeed() + 1);
        speedTestResult.setDelay(mSpeedTestInfo.getPing());
        speedTestResult.setDl(mSpeedTestInfo.getDlSpeed());
        speedTestResult.setUp(mSpeedTestInfo.getUploadSpeed());
        double dlSpeed = mSpeedTestInfo.getDlSpeed();
        int gameScore = 0, shortVideoScore = 0, videoScore = 0;
        Random random = new Random();
        if (dlSpeed < 5) {
            gameScore = 60 + random.nextInt(10);
            shortVideoScore = 60 + random.nextInt(10);
            videoScore = 60 + random.nextInt(10);
        } else if (dlSpeed < 10) {
            gameScore = 70 + random.nextInt(10);
            shortVideoScore = 70 + random.nextInt(10);
            videoScore = 70 + random.nextInt(10);
        } else if (dlSpeed < 20) {
            gameScore = 80 + random.nextInt(10);
            shortVideoScore = 80 + random.nextInt(10);
            videoScore = 80 + random.nextInt(10);
        } else {
            gameScore = 90 + random.nextInt(11);
            shortVideoScore = 90 + random.nextInt(11);
            videoScore = 90 + random.nextInt(11);
        }
        speedTestResult.setGameScore(gameScore);
        speedTestResult.setMovieScore(videoScore);
        speedTestResult.setShortVideoScore(shortVideoScore);
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                ResultHelper.showSpeedTestResult(mContext, speedTestResult);
            }
        }, 2000);
    }

    private void pintData(SpeedTestStepInfo.PingData pingData) {
        if (pingData != null) {
            DecimalFormat decimalFormat = new DecimalFormat("##.##");
            mTvPing.setText(decimalFormat.format(pingData.ping));
            mTvJitter.setText(decimalFormat.format(pingData.jetter));
//            mTvPacketLose.setText(decimalFormat.format(pingData.lose));
            mSpeedTestInfo.setPing(pingData.ping);
            mSpeedTestInfo.setJetter(pingData.jetter);
            mSpeedTestInfo.setLoseRate(pingData.lose);
        }
    }

    private void loseRateData(double loseRate) {
        DecimalFormat decimalFormat = new DecimalFormat("##.##");
        mTvPacketLose.setText(decimalFormat.format(loseRate));
        mSpeedTestInfo.setLoseRate(loseRate);
    }

    private void startTest() {
        mRlTestMain.setVisibility(View.VISIBLE);
        resetSpeedView();
        String netName = NetInfoUtils.getNetName(Utils.getApp());
        mSpeedTestInfo.setNetName(netName);
        mSpeedTestInfo.setNetType(NetInfoUtils.getNetworkState(Utils.getApp()));
        mSpeedTestInfo.setInnerIp(NetInfoUtils.getLocaleIp(Utils.getApp()));
        mSpeedTestView.prepare(new SpeedTestView3.PrepareCallBack() {
            @Override
            public void onPrepared() {
                mSpeedTestViewModel.startSpeedTest();
            }
        });
    }

    private void endSpeed() {
        resetSpeedView();
        mSpeedTestInfo.reset();
        mSpeedTestViewModel.endSpeedTest();
    }


    @Override
    public void onDestroy() {
        endSpeed();
        mHandler.removeCallbacksAndMessages(null);
        super.onDestroy();
    }

    private void resetSpeedView() {
        mTvDownloadSpeed.setText("-");
        mTvSpeedDataUse.setText("-");
        mLineChartDownload.reset();
        mTvUploadSpeed.setText("-");
        mTvUploadDataUse.setText("-");
        mLineChartUpload.reset();
        mTvPing.setText("—");
        mTvJitter.setText("—");
        mTvPacketLose.setText("—");
        mTvCurrentSpeed.setText("0.0");
        mSpeedTestView.setCreditValue(0);
        mDuProgressView.reset();
    }
}
